'use strict'

let util = require('util');
let Fiber = require('fibers');

let csv = require('../modules/lib/csv');
let CsvParser = csv.CsvParser;
let redis = require('../modules/lib/redis');
let outputLogger = require('../modules/lib/loggers').output;
let DATA_SYNC_DB = 1;
let DATA_SYNC_KEY = 'attendance_data_sync';
let TEST_SYNC_KEY = 'test_data_sync';
let TIMEOUT = 2000;

let models = require('../modules/models');

let User = models.User;
let Role = models.Role;
let School = models.School;
let NatureClass = models.NatureClass;
let Student = models.Student;
let Teacher = models.Teacher;
let Grade = models.Grade;
let Attendance = models.Attendance;
let AttendanceValue = models.AttendanceValue;
let AttendanceStatus = models.AttendanceStatus;

let UserDao = models.UserDao;
let RoleDao = models.RoleDao;
let SchoolDao = models.SchoolDao;
let NatureClassDao = models.NatureClassDao;
let StudentDao = models.StudentDao;
let TeacherDao = models.TeacherDao;
let GradeDao = models.GradeDao;
let AttendanceDao = models.AttendanceDao;
let AttendanceValueDao = models.AttendanceValueDao;

let checkTimeSetService = require('../modules/services/checktimeset');

let ROLE_ID_STUDENT = '2300000001000000002';
let ROLE_ID_TEACHER = '2300000001000000003';

function importData() {
    Fiber(() => {
        UserDao.remove({});
        SchoolDao.remove({});
        NatureClassDao.remove({});
        StudentDao.remove({});
        TeacherDao.remove({});
        GradeDao.remove({});
        AttendanceDao.remove({});
        AttendanceValueDao.remove({});

        importSchools();
        importClasses();
        importUsers();

        process.exit();
    }).run();
}
function importSchools() {
    let csvParser = new CsvParser();

    let schoolRecords = csvParser.parseFile('utils/data/ifly/school.csv');
    schoolRecords.forEach(data => {
        insertSchool(data);
    });
}

function importClasses() {
    let csvParser = new CsvParser();

    let classRecords = csvParser.parseFile('utils/data/ifly/class.csv');
    classRecords.forEach(data => {
        insertNatureClass(data);
    });
}

function importUsers() {
    let csvParser = new CsvParser();

    let userRecords = csvParser.parseFile('utils/data/ifly/user.csv');
    userRecords.forEach(data => {
        let user = insertUser(data);
        if ( user.role.name == 'student' ) {
            insertStudent(user, data);
        }
        else {
            insertTeacher(user, data);
        }
    });
}

function insertUser(data) {
    let user = UserDao.findOne({
        iflyId: data.id
    });

    if ( user ) {
        return user;
    }

    user = new User({
        iflyId: data.id,
        name: data.loginName,
        realName: data.userName,
        status: 1
    });

    if ( data.roleId == ROLE_ID_STUDENT ) {
        user.role = getRole('student');
    }
    else {
        user.role = getRole('teacher');
    }

    UserDao.create(user);
    outputLogger.info(util.format('Insert user: %s', user.iflyId));

    return user;
}

function insertStudent(user, data) {
    let student = new Student({
        name: user.realName,
        user: user,
        attendCount: 0,
        totalAbsence: 0,
        lateCount: 0,
        absenceCount: 0,
        restCount: 0,
        earlyCount: 0
    });

    StudentDao.create(student);

    let natureClass = NatureClassDao.findOne({
        iflyId: data.classId
    });

    if ( !natureClass ) {
        outputLogger.error(util.format('Nature Class %s not found', data.class_id));
        return;
    }

    NatureClassDao.update({
        iflyId: data.classId
    }, {
        $push: {
            students: student.id
        }
    });

    outputLogger.info(util.format('Insert student: %s', user.iflyId));

    // 创建考勤数据
    let today = new Date();
    today.setHours(0);
    today.setMinutes(0);
    today.setSeconds(0);
    for ( let dayIndex = 0; dayIndex < 7; dayIndex ++ ) {
        let attendance = new Attendance({
            student: student,
            date: today,
            values: [
                new AttendanceValue({
                    enterStatus: AttendanceStatus.Attended,
                    exitStatus: AttendanceStatus.Attended
                }),
                new AttendanceValue({
                    enterStatus: generateAttendanceValue([
                        AttendanceStatus.Attended,
                        AttendanceStatus.Late
                    ]),
                    exitStatus: generateAttendanceValue([
                        AttendanceStatus.Attended,
                        AttendanceStatus.Early
                    ])
                }),
                new AttendanceValue({
                    enterStatus: AttendanceStatus.Created,
                    exitStatus: AttendanceStatus.Created
                })
            ]
        });

        attendance.values.forEach(value => AttendanceValueDao.create(value));
        AttendanceDao.create(attendance);

        today = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);
    }
}

function generateAttendanceValue(candidation) {
    let index = Math.floor(Math.random() * candidation.length);

    return candidation[index];
}

function insertTeacher(user, data) {
    let teacher = TeacherDao.findOne({
        user: user
    });

    if ( !teacher ) {
        teacher = new Teacher({
            name: user.realName,
            user: user,
        });

        TeacherDao.create(teacher);
    }

    if ( data.classId ) {
        let natureClass = NatureClassDao.findOne({
            iflyId: data.classId
        });

        if ( !natureClass ) {
            outputLogger.error(util.format('Nature Class %s not found', data.class_id));
            return;
        }

        TeacherDao.update({
            id: teacher.id
        }, {
            $push: {
                managedClasses: natureClass.id
            }
        });
    }
    else if ( data.schoolId ) {
        let school = SchoolDao.findOne({
            iflyId: data.schoolId
        });

        if ( !school ) {
            outputLogger.error(util.format('School %s not found', data.schoolId));
            return;
        }

        TeacherDao.update({
            id: teacher.id
        }, {
            $set: {
                managedSchool: school.id
            }
        });

        user.role = getRole('leader');
        UserDao.update(user);
    }

    outputLogger.info(util.format('Insert teacher: %s', user.iflyId));
}

function insertSchool(data) {
    let school = new School({
        iflyId: data.id,
        name: data.schoolName,
        checkTimeSet: checkTimeSetService.createInstance()
    });

    SchoolDao.create(school);
    outputLogger.info(util.format('Insert school: %s', school.iflyId));
}

function insertNatureClass(data) {
    let natureClass = new NatureClass({
        iflyId: data.id,
        name: data.className
    });

    NatureClassDao.create(natureClass);

    let gradeName = data.year + '级';
    let grade = GradeDao.findOne({
        iflySchoolId: data.schoolId,
        name: gradeName
    });

    if ( !grade ) {
        grade = new Grade({
            iflySchoolId: data.schoolId,
            name: gradeName,
            natureClasses: [],
            checkTimeSet: checkTimeSetService.createInstance()
        });

        GradeDao.create(grade);

        let school = SchoolDao.findOne({
            iflyId: data.schoolId
        });

        if ( !school ) {
            outputLogger.error(util.format('School %s not found', data.schoolId));
            return;
        }

        school.grades.push(grade);
        SchoolDao.update(school);
    }

    grade.natureClasses.push(natureClass);
    GradeDao.update(grade);

    outputLogger.info(util.format('Insert nature class: %s', natureClass.iflyId));
}

function getRole(roleName) {
    return RoleDao.findOne({
        name: roleName
    });
}

importData();
